package org.smile.util;

import java.io.Serializable;
import java.net.InetAddress;
import java.util.Date;

/**
 * UUid生成器 
 */
public class UUIDGenerator {
	/**
	 * 本机的IP地址
	 */
	private static final int IP;
	
	private final static String sep = "";
	
	private  static int IptoInt(byte[] bytes) {
		int result = 0;
		for (int i = 0; i < 4; i++) {
			result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
		}
		return result;
	}

	static {
		int ipadd;
		try {
			ipadd = IptoInt(InetAddress.getLocalHost().getAddress());
		} catch (Exception e) {
			ipadd = 0;
		}
		IP = ipadd;
	}
	
	private static short counter = (short) 0;
	
	private static final int JVM = (int) (System.currentTimeMillis() >>> 8);

	private  UUIDGenerator() {
	}
	/**
	 * Unique across JVMs on this machine (unless they load this class in the
	 * same quater second - very unlikely)
	 */
	protected int getJVM() {
		return JVM;
	}

	/**
	 * Unique in a millisecond for this JVM instance (unless there are >
	 * Short.MAX_VALUE instances created in a millisecond)
	 */
	protected short getCount() {
		synchronized (UUIDGenerator.class) {
			if (counter < 0)
				counter = 0;
			return counter++;
		}
	}

	/**
	 * Unique in a local network
	 */
	protected int getIP() {
		return IP;
	}

	/**
	 * Unique down to millisecond
	 */
	protected short getHiTime() {
		return (short) (System.currentTimeMillis() >>> 32);
	}

	protected int getLoTime() {
		return (int) System.currentTimeMillis();
	}

	protected static String format(int intval) {
		String formatted = Integer.toHexString(intval);
		StringBuffer buf = new StringBuffer("00000000");
		buf.replace(8 - formatted.length(), 8, formatted);
		return buf.toString();
	}
	/**
	 * integer 转为10位16进制
	 * @param intval
	 * @return
	 */
	protected static String formatLong(int intval) {
		String formatted = NumberUtils.toString(intval,64);
		StringBuffer buf = new StringBuffer("0000000");
		buf.replace(7 - formatted.length(),7, formatted);
		return buf.toString();
	}
	/**
	 * 转为4位16进制 
	 * @param shortval
	 * @return
	 */
	protected static String format(short shortval) {
		String formatted = Integer.toHexString(shortval);
		StringBuffer buf = new StringBuffer("0000");
		buf.replace(4 - formatted.length(), 4, formatted);
		return buf.toString();
	}
	
	/**
	 * 一个新的32位的UUID
	 * @return
	 */
	private  Serializable generate(){
		return new StringBuffer(36).append(format(getIP())).append(sep).append(
				format(getJVM())).append(sep).append(format(getHiTime()))
				.append(sep).append(format(getLoTime())).append(sep).append(
						format(getCount())).toString();
	}
	/**
	 * 
	 * @param flagStr
	 * @return
	 */
	public static String encodeFlag(String flagStr){
		if(flagStr==null){
			return "";
		}else{
			return formatLong(flagStr.hashCode());
		}
	}
	/**
	 * @param flagStr
	 * @return
	 */
	private Serializable longUUid(String flagStr){
		return new StringBuffer(54).append(encodeFlag(flagStr)).append(sep).append(NumberUtils.toString(System.currentTimeMillis(), 64)).append(sep).append(shortUUid());
	}
	/**
	 * 仓建一个新的UUid
	 * @return
	 */
	public static String createUUid(){
		return String.valueOf(new UUIDGenerator().generate());
	}
	/**
	 * 仓建一个新的UUid
	 * @return
	 */
	public static String createLongUUid(String str){
		return String.valueOf(new UUIDGenerator().longUUid(str));
	}
	/**
	 * 仓建一个新的UUid
	 * @return
	 */
	public static String createLongUUid(){
		return String.valueOf(new UUIDGenerator().longUUid(null));
	}
	/**
	 * 从54位的uuid中查看此uuid创建是指定的标志
	 * @param uuid
	 * @return
	 */
	public static String getUUidFlag(String uuid){
		return uuid.substring(0, 7);
	}
	/**
	 * 从一个54位的uuid中查看些id创建的时时间
	 * @param uuid
	 * @return
	 */
	public static Date getUUidDate(String uuid){
			return new Date(NumberUtils.parseLong(uuid.substring(7, uuid.length()-22),64));
	}
	/**
	 *短uuid 是以64进制表示的字符串
	 *在原16进制的uuid基础之后转换而来
	 */
	public static String shortUUid(){
		StringBuffer sb=new StringBuffer(20);
		//用于确定二位
		StringBuffer bit2=new StringBuffer("00");
		String uuid=createUUid();
		int endIndex=0;
		//把原来的16进制的3位转成64进制的2位
		for(int i=0;i<=uuid.length()/3;i++){
			endIndex=(i+1)*3;
			if(endIndex>uuid.length()){
				endIndex=uuid.length();
			}
			String temp=uuid.substring(i*3,endIndex);
			String temp2=NumberUtils.toString(Long.parseLong(temp, 16), 64);
			bit2.replace(2 - temp2.length(), 2, temp2);
			sb.append(bit2.toString());
			//还原二位格式
			bit2.replace(0, 2, "00");
		}
		return sb.toString();
	}
	/**
	 * @return
	 */
	private String createsmileUUid(int radix,String sep){
		return new StringBuffer(36).append(NumberUtils.toString(getIP(),radix)).append(sep).append(
				NumberUtils.toString(getJVM(),radix)).append(sep).append(sep).append(NumberUtils.toString(getCount(),radix)).append(sep).append(
						NumberUtils.toString(System.currentTimeMillis(),radix)).toString();
	}
	/**
	 * smile 定义策略生成
	 * @return
	 */
	public static String smileUUid(){
		return new UUIDGenerator().createsmileUUid(62,sep);
	}
	
}
